﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;

public class EnhancedSerialTerminal
{
    private class SerialPortContext
    {
        public SerialPort Port { get; set; }
        public bool IsOpen => Port?.IsOpen ?? false;
        public List<string> Logs { get; } = new List<string>();
    }

    private static Dictionary<string, SerialPortContext> ports = new Dictionary<string, SerialPortContext>();
    private static bool isRunning = true;

    public static void Main()
    {
        InitializePorts();
        DisplayMainMenu();

        while (isRunning)
        {
            HandleUserInput();
        }

        CloseAllPorts();
    }

    private static void InitializePorts()
    {
        Console.WriteLine("=== 多串口通信终端 ===");

        foreach (var portName in SerialPort.GetPortNames())
        {
            var context = new SerialPortContext
            {
                Port = new SerialPort(portName)
                {
                    BaudRate = 115200,
                    DataBits = 8,
                    StopBits = StopBits.One,
                    Parity = Parity.None,
                    Handshake = Handshake.None,
                    ReadTimeout = 1000,
                    WriteTimeout = 1000
                }
            };

            ports.Add(portName, context);
            Console.WriteLine($"已初始化端口：{portName}");
        }
    }

    private static void DisplayMainMenu()
    {
        Console.WriteLine("\n主菜单选项：");
        Console.WriteLine("1. 查看端口状态");
        Console.WriteLine("2. 配置串口参数");
        Console.WriteLine("3. 打开/关闭端口");
        Console.WriteLine("4. 查看通信日志");
        Console.WriteLine("5. 发送数据");
        Console.WriteLine("0. 退出程序");
        Console.Write("请选择操作：");
    }

    private static void HandleUserInput()
    {
        switch (Console.ReadLine())
        {
            case "1":
                ShowPortStatus();
                break;
            case "2":
                ConfigurePort();
                break;
            case "3":
                TogglePort();
                break;
            case "4":
                ShowCommunicationLogs();
                break;
            case "5":
                SendData();
                break;
            case "0":
                isRunning = false;
                break;
            default:
                Console.WriteLine("无效输入");
                break;
        }
    }

    private static void ShowPortStatus()
    {
        Console.WriteLine("\n当前端口状态：");
        foreach (var port in ports.Values)
        {
            Console.WriteLine($"[{port.Port.PortName}]");
            Console.WriteLine($"  状态：{(port.IsOpen ? "已开启" : "已关闭")}");
            Console.WriteLine($"  波特率：{port.Port.BaudRate}");
            Console.WriteLine($"  数据位：{port.Port.DataBits}");
            Console.WriteLine($"  停止位：{port.Port.StopBits}");
            Console.WriteLine($"  校验位：{port.Port.Parity}");
        }
    }

    private static void ConfigurePort()
    {
        Console.Write("请输入要配置的端口号：");
        var portName = Console.ReadLine().ToUpper();

        if (ports.TryGetValue(portName, out var context))
        {
            Console.Write($"新波特率（当前：{context.Port.BaudRate}）：");
            if (int.TryParse(Console.ReadLine(), out int baudRate))
                context.Port.BaudRate = baudRate;

            Console.WriteLine("配置已更新");
        }
        else
        {
            Console.WriteLine("端口不存在");
        }
    }

    private static void TogglePort()
    {
        Console.Write("请输入端口号：");
        var portName = Console.ReadLine().ToUpper();

        if (ports.TryGetValue(portName, out var context))
        {
            if (context.IsOpen)
            {
                context.Port.Close();
                LogMessage(portName, "端口已关闭");
            }
            else
            {
                try
                {
                    context.Port.Open();
                    new Thread(() => ReceiveData(context)).Start();
                    LogMessage(portName, "端口已开启");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"开启失败：{ex.Message}");
                }
            }
        }
        else
        {
            Console.WriteLine("端口不存在");
        }
    }

    private static void ReceiveData(SerialPortContext context)
    {
        while (context.IsOpen)
        {
            try
            {
                string data = context.Port.ReadLine();
                LogMessage(context.Port.PortName, $"收到数据：{data} ({data.Length}字节)");
            }
            catch (TimeoutException) { }
        }
    }

    private static void SendData()
    {
        Console.Write("目标端口：");
        var portName = Console.ReadLine().ToUpper();

        if (ports.TryGetValue(portName, out var context) && context.IsOpen)
        {
            Console.Write("发送内容：");
            string message = Console.ReadLine();
            context.Port.WriteLine(message);
            LogMessage(portName, $"发送数据：{message} ({message.Length}字节)");
        }
        else
        {
            Console.WriteLine("端口未开启或不存在");
        }
    }

    private static void ShowCommunicationLogs()
    {
        Console.Write("查看日志的端口号（ALL显示全部）：");
        var filter = Console.ReadLine().ToUpper();

        foreach (var port in ports.Values)
        {
            if (filter == "ALL" || port.Port.PortName == filter)
            {
                Console.WriteLine($"\n[{port.Port.PortName}] 通信记录：");
                foreach (var log in port.Logs)
                {
                    Console.WriteLine(log);
                }
            }
        }
    }

    private static void LogMessage(string portName, string message)
    {
        var logEntry = $"[{DateTime.Now:yyyy/MM/dd | HH:mm:ss.fff}] {message}";
        ports[portName].Logs.Add(logEntry);
        Console.WriteLine(logEntry);
    }

    private static void CloseAllPorts()
    {
        foreach (var port in ports.Values)
        {
            if (port.IsOpen) port.Port.Close();
        }
    }
}